package aupdg.logic.analysis.impl;

import aupdg.data.model.Edge;
import aupdg.data.model.Ldg;
import aupdg.data.model.Node;
import aupdg.data.model.impl.AuDataDependenceEdge;
import aupdg.logic.analysis.InformationLeakAnalysis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Find explicit information leaks in the LDG.
 *
 * @author AA and CJ
 */
public class ExplicitILAnalysis implements InformationLeakAnalysis {

    private Ldg ldg;

    /**
     * Constructor. Uses internally an LDG object.
     *
     * @param ldg
     */
    public ExplicitILAnalysis(Ldg ldg) {
        this.ldg = ldg;
    }

    @Override
    public Map<Node, List<List<Node>>> detectInformationLeaks() {

        HashMap<Node, List<List<Node>>> infoLeaksMap = new HashMap<Node, List<List<Node>>>();
        List<Edge> dataDepEdges = this.ldg.getDataDepEdges();

        for (int i = 0; i < dataDepEdges.size(); i++) {
            AuDataDependenceEdge dataDepEdge = (AuDataDependenceEdge) dataDepEdges.get(i);
            Node source = dataDepEdge.getSource();
            Node target = dataDepEdge.getTarget();

            System.out.println(target.getLevel());
            List<List<Node>> pathWithLeaks = new ArrayList<List<Node>>();

            for (int j = 0; j < dataDepEdge.getDataObjects().size(); j++) {
                List<Node> path = new ArrayList<Node>();
                //Ver si se puede agregar comparacion con > en SecuritLevel class
                if (dataDepEdge.getDataObjects().get(j).getSecurityLevel().intValue > target.getLevel().intValue) {
                    //Explicit information leak found
                    //Instance of explicit information leak can also be obtained. Change presentation to show more values
                    //on the information leaks results.
                    System.out.println("Explicit InfoLeak between: " + source + "(" + source.getLevel() + ")"
                            + " -> " + target + "(" + target.getLevel() + ")"
                            + " DataObject" + "(" + dataDepEdge.getDataObjects().get(j).getSecurityLevel() + ")"
                            + " Instance: " + dataDepEdge.getInstances().get(j));
                    pathWithLeaks.add(path);
                    path.add(source);
                    path.add(target);
                    infoLeaksMap.put(target, pathWithLeaks);
                }
            }
        }
        return infoLeaksMap;
    }
}
